package com.jackrain.nea.omslocal.Dao;

import com.alibaba.dubbo.common.utils.NetUtils;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.util.TypeUtils;
import com.jackrain.nea.config.PropertiesConf;
import com.jackrain.nea.omslocal.service.LocalLogService;
import com.jackrain.nea.omslocal.service.SendMqServies;
import com.jackrain.nea.omslocal.util.JsonKeyCheck;
import com.jackrain.nea.omslocal.util.RegexDateUtil;
import com.jackrain.nea.util.ApplicationContextHandle;
import com.jackrain.nea.util.Tools;
import com.jackrain.nea.util.Validator;
import com.jackrain.nea.web.query.QueryEngine;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.time.FastDateFormat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.text.ParseException;
import java.util.*;

/**
 * Description: 保存淘宝分销订单数据
 * Created with IntelliJ IDEA.
 * User: cs
 * Date: 2017/3/31
 * Time: 21:43
 */
@Component
@Slf4j
public class TaoBaoFxOrder {

    @Autowired
    private RegexDateUtil regexDate;
    private FastDateFormat fastformat = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss");
    @Autowired
    private LocalLogService localLogService;

    @Autowired
    private SendMqServies sendMq;

    /**
     * 保存订单的总方法
     *
     * @param taobaoorderArr
     * @param topic
     */
    public void orderStart(JSONArray taobaoorderArr, String msgkey, String topic) throws Exception {
        TaoBaoFxOrder taoBaoFxOrder = ApplicationContextHandle.getBean(TaoBaoFxOrder.class);
        PropertiesConf pconf = (PropertiesConf) ApplicationContextHandle.getBean("propertiesConf");
        // 定义接收消费日志信息的 jsonobject
        JSONObject infoObj = new JSONObject();
        List tids = new ArrayList();
        int countFaild = 0;
        Long fenxiao_id = 0L;
        //  需要解析分销订单结构,分离数据
        for (Object obj : taobaoorderArr) {

            JSONObject tempObj = new JSONObject();
            // 定以解析分销主表的 jsonObject
            JSONObject reciveObj = new JSONObject();
            // 定义接收明细表的 JSONArray
            JSONArray fxProducteArr = new JSONArray();
            try {
                // 循环遍历拿到单条分销订单数据
                tempObj = JSONObject.parseObject(obj.toString(), Feature.OrderedField);
                JSONArray tempArr = tempObj.getJSONObject("jdp_response").getJSONObject("fenxiao_orders_get_response").getJSONObject("purchase_orders").getJSONArray("purchase_order");
                //JSONArray tempArr = tempObj.getJSONObject("fenxiao_orders_get_response").getJSONObject("purchase_orders").getJSONArray("purchase_order");
                // 主订单固定只有一条
                JSONObject tempJosn = (JSONObject) tempArr.get(0);

                if (tempJosn.getJSONObject("sub_purchase_orders") != null) {
                    // 明细表数据
                    fxProducteArr = tempJosn.getJSONObject("sub_purchase_orders").getJSONArray("sub_purchase_order");
                }

                tempJosn.remove("sub_purchase_orders");
                reciveObj = tempJosn.getJSONObject("receiver");
                tempJosn.remove("receiver");
                // 主表数据
                tempJosn.putAll(reciveObj);
                fenxiao_id = tempJosn.getLong("fenxiao_id");
                log.debug(fenxiao_id.toString()+"<=====");
                // 根据 fenxiao_id 查询数据库,判断该数据是 新增 或是 修改
                String selectSql = "SELECT id FROM T_OMSFENXIAOORDER WHERE fenxiao_id = ?";
                int id = Tools.getInt(QueryEngine.getInstance().doQueryOne(selectSql, new Object[]{fenxiao_id}), -1);
                log.debug(id+"<=======");
                int idd = QueryEngine.getInstance().doQueryInt(selectSql,new Object[]{fenxiao_id});
                log.debug(idd +"<=====");
                if (id < 0) {
                    // 新增数据
                    // 数据不为空 保存数据
                    taoBaoFxOrder.insert(tempJosn, fxProducteArr, topic);
                    // 将消费的数据保存到数据库
                    localLogService.insertLogDeatail(tempJosn, fenxiao_id, 1, topic, msgkey);

                } else {

                    taoBaoFxOrder.update(tempJosn, fxProducteArr, id, topic);
                    // 保存消费具体信息
                    localLogService.insertLogDeatail(tempJosn, fenxiao_id, 2, topic, msgkey);

                }
                tids.add(fenxiao_id);
            } catch (Exception e) {

                // 逐条将错误信息以消息发送到线上发送到线上
                // 获取 流
                StringWriter sw = new StringWriter();
                PrintWriter pw = new PrintWriter(sw);
                JSONObject errObj = new JSONObject();
                errObj.put("bus_id", fenxiao_id);
                errObj.put("tablename", pconf.getProperty("ons.fxorder"));
                errObj.put("topic", topic);
                errObj.put("tag", pconf.getProperty("ons.comp"));
                errObj.put("msgkey", msgkey);
                // 线下消费报错的主机 ip
                errObj.put("client_ip", NetUtils.getLocalAddress());
                // 将错误以流写出
                e.printStackTrace(pw);
                errObj.put("errmsg", sw.toString());

                errObj.put("protime", System.currentTimeMillis());
                errObj.put("code",-1);
                sendMq.sendMqinfoObj(errObj, pconf.getProperty("ons.loginfor.err.topic"), pconf.getProperty("ons.loginfor.err.tag"));
                // 处理异常  将错误信息
                countFaild++;
                localLogService.insertLog(sw.toString(), tempObj, fenxiao_id, topic, msgkey);

            }
            // 消费完成,将消费的消息信息发送至线上,更新线上日志表
            // 调用更新线上日志的服务
            infoObj.put("msgkey", msgkey);
            infoObj.put("topic", topic);
            infoObj.put("countsuccess", (taobaoorderArr.size() - countFaild));
            infoObj.put("protime", System.currentTimeMillis());
            infoObj.put("client_ip", NetUtils.getLocalAddress());
            infoObj.put("tids",tids);
            infoObj.put("code",0);
            infoObj.put("total",taobaoorderArr.size());
            // 消费完成,将消费的消息信息发送至线上,更新线上日志表
            // 参数 1 消息体  2 消息 topic  3 消息 tag
            String msgId = sendMq.sendMqinfoObj(infoObj, pconf.getProperty("ons.loginfor.suf.topic"), pconf.getProperty("ons.loginfor.suf.tag"));
            if("-1".equals(msgId)){
                for(int i = 0; i < 3; i++){
                    if(!"-1".equals(msgId)){
                        break;
                    }
                    //重试回执
                    msgId = sendMq.sendMqinfoObj(infoObj, pconf.getProperty("ons.loginfor.suf.topic"), pconf.getProperty("ons.loginfor.suf.tag"));
                }
            }
            log.debug("taobaofxorder消费完成回执 msgId= {}, topic= {}, tag= {}", msgId, pconf.getProperty("ons.loginfor.suf.topic"), pconf.getProperty("ons.loginfor.suf.tag"));
        }
    }

    @Transactional
    public void insert(JSONObject tempJosn, JSONArray ordersArr, String topic) throws Exception {
        Object outId = null;
        // 新增数据
        // 数据不为空 保存数据
        if (!tempJosn.isEmpty()) {
            Map map = null;
            map = saveFxOrder(tempJosn);
            outId = map.get("seq");
        } else {
            log.debug("主表数据为空");
        }
        if (ordersArr != null) {
            log.debug("drders 订单商品明细");
            saveFxOrderDetal(ordersArr, "T_OMSFENXIAOPRODUCT", outId);
        } else {
            log.debug("drders 订单商品明细表为空");
        }
        // 在执行完之后需要更改主表的 istrans 字段为 0
        String sql = "update T_OMSFENXIAOORDER SET istrans = 0 WHERE id = ?";
        QueryEngine.getInstance().executeUpdate(sql, new Object[]{outId});

    }

    @Transactional
    public void update(JSONObject tempObj, JSONArray ordersArr, int id, String topic) throws Exception {


        // 数据不为空 保存数据
        if (!tempObj.isEmpty()) {
            // 根据查询到的 id 更新主表数据
            updateFxOrder(tempObj, id);
        } else {
            log.error("分销主表数据为空");
            return;
        }
        if (ordersArr != null) {
            // 更新子表 订单商品明细表数据
            updateFxOrderDetal(ordersArr, "T_OMSFENXIAOPRODUCT", "fenxiao_id");
        } else {
            log.debug("drders 分销订单商品明细表为空");
        }

        // 更新操作之后需要更新 istrans 为0
        String sql = "update T_OMSFENXIAOORDER SET istrans = 0 WHERE id = ?";
        QueryEngine.getInstance().executeUpdate(sql, new Object[]{id});

    }


    /**
     * 保存分销订单主表
     *
     * @param jsonObj
     * @return
     * @throws SQLException
     */
    public Map saveFxOrder(JSONObject jsonObj) throws SQLException, ParseException {

        JsonKeyCheck checkjson = (JsonKeyCheck) ApplicationContextHandle.getBean(JsonKeyCheck.class);
        jsonObj = checkjson.checkJsonkeycache(jsonObj, "T_OMSFENXIAOORDER", checkjson.getInsertcolsmap());
        Map map = new HashMap();

        // 将固定需要维护的字段加入 jsonObj,  creatTime, modified , outstatus
        Date nowDate = new Date();
        Timestamp nowTime = new Timestamp(nowDate.getTime());
        // 获取主表的 sequences
        String squnceSql = "select get_wsequences('T_OMSFENXIAOORDER') as SEQ from dual";
        Long id = TypeUtils.castToLong(QueryEngine.getInstance().doQueryOne(squnceSql));
        jsonObj.put("id", id);
        jsonObj.put("modified", nowTime);


        String columnName = "";
        String columnValue = "";
        Set set = jsonObj.keySet();
        Object[] objArr = jsonObj.values().toArray();
        log.debug(objArr.toString());
        for (Object obj1 : set) {
            columnName = columnName + "," + obj1;
        }
        columnName = columnName.substring(1);

        for (int i = 0; i < objArr.length; i++) {

            if (objArr[i] instanceof String) {
                if (regexDate.regexDate(((String) objArr[i]))) {
                    Date date = fastformat.parse(((String) objArr[i]));
                    objArr[i] = date;
                }
            }
            columnValue = columnValue + ",?";
        }

        columnValue = columnValue.substring(1);

        String sql = "insert into T_OMSFENXIAOORDER (" + columnName + ") values (" + columnValue + ")";
        log.debug(sql + "=========================");
        int code = QueryEngine.getInstance().executeUpdate(sql, objArr);
        log.debug(objArr.toString());

        map.put("code", code);
        map.put("seq", id);
        return map;
    }

    /**
     * 保存分销订单子表,商品表
     *
     * @param dataArr
     * @return
     * @throws SQLException
     */

    public int saveFxOrderDetal(JSONArray dataArr, String tableName, Object outObj) throws SQLException, ParseException {

        for (Object obj : dataArr) {

            JSONObject jsonObj = JSONObject.parseObject(obj.toString(), Feature.OrderedField);

            JsonKeyCheck checkjson = (JsonKeyCheck) ApplicationContextHandle.getBean(JsonKeyCheck.class);
            jsonObj = checkjson.checkJsonkeycache(jsonObj, "T_OMSFENXIAOPRODUCT", checkjson.getInsertcolsmap());
            // 将固定需要维护的字段加入 jsonObj,  creatTime, modified , outstatus
            // outstatus 默认值为 1 ,当主表所有明细更新完成,将此状态更改为 2 ;

            // 获取子表的 sequences
            String squnceSql = "select get_wsequences('" + tableName + "') as SEQ from dual";
            int id = TypeUtils.castToInt(QueryEngine.getInstance().doQueryOne(squnceSql));

            jsonObj.put("id", id);
            jsonObj.put("omsfenxiaoorderid", outObj);
            String columnName = "";
            String columnValue = "";
            Set set = jsonObj.keySet();
            Object[] objArr = jsonObj.values().toArray();

            for (Object obj1 : set) {
                columnName = columnName + "," + obj1;
            }
            columnName = columnName.substring(1);

            for (int i = 0; i < objArr.length; i++) {

                if (objArr[i] instanceof String) {
                    if (regexDate.regexDate(((String) objArr[i]))) {
                        Date date2 = fastformat.parse(((String) objArr[i]));
                        objArr[i] = date2;
                    }
                }
                columnValue = columnValue + ",?";
            }
            columnValue = columnValue.substring(1);

            String sql = "insert into " + tableName + " (" + columnName + ") values (" + columnValue + ")";
            log.debug("sql =========>" + sql);
            log.debug("======================>"+jsonObj.toString());
            int code = QueryEngine.getInstance().executeUpdate(sql, objArr);

        }
        return dataArr.size();
    }


    /**
     * 更新分销订单主表
     *
     * @param jsonObj
     * @return
     * @throws SQLException
     */
    public Map updateFxOrder(JSONObject jsonObj, int id) throws SQLException, ParseException {

        JsonKeyCheck checkjson = (JsonKeyCheck) ApplicationContextHandle.getBean(JsonKeyCheck.class);

        jsonObj = checkjson.checkJsonkeycache(jsonObj, "T_OMSFENXIAOORDER", checkjson.getUpdatecolsmap());

        Map map = new HashMap();

        String params = "";
        Set set = jsonObj.keySet();
        Object[] objArr = jsonObj.values().toArray();
        for (Object obj1 : set) {
            Object tempobject = jsonObj.get(obj1);
            params = params + "" + obj1 + " = ?,";
        }

        for (int i = 0; i < objArr.length; i++) {

            if (Validator.isNull(objArr[i])) {
                objArr[i] = "null";
            }
            if (objArr[i] instanceof String) {
                if (regexDate.regexDate(((String) objArr[i]))) {
                    Date date2 = fastformat.parse(((String) objArr[i]));
                    objArr[i] = date2;
                }
            }
        }

        params = params.substring(0, params.length() - 1);

        String sql = "update T_OMSFENXIAOORDER set " + params + " where id = ?";
        log.debug("sql =========>" + sql);
        log.debug("======================>"+jsonObj.toString());
        int code = QueryEngine.getInstance().executeUpdate(sql, ArrayUtils.add(objArr, id));

        return map;
    }

    /**
     * 更新分销订单子表
     *
     * @param dataArr
     * @return
     * @throws SQLException
     */
    public int updateFxOrderDetal(JSONArray dataArr, String tableName, String outkey) throws SQLException, ParseException {


        for (Object obj : dataArr) {
            JSONObject jsonObj = JSONObject.parseObject(obj.toString(), Feature.OrderedField);

            JsonKeyCheck checkjson = (JsonKeyCheck) ApplicationContextHandle.getBean(JsonKeyCheck.class);

            log.debug(jsonObj.toJSONString() + "fenxiao before");
            jsonObj = checkjson.checkJsonkeycache(jsonObj, "T_OMSFENXIAOPRODUCT", checkjson.getUpdatecolsmap());
            log.debug(jsonObj.toJSONString() + "fenxiao after");
            // 根据唯一外键查询判断 该数据是否存在,存在就更新数据
            String selectSql = "select id from " + tableName + " where " + outkey + " = ?";
            int id = Tools.getInt((QueryEngine.getInstance().doQueryOne(selectSql, new Object[]{jsonObj.getLong(outkey)})), -1);

            if (id < 0) {
                // 数据不存在
                log.debug(outkey + ":" + jsonObj.get(outkey));
                continue;
            }
//            Date nowDate = new Date();
//            Timestamp nowTime = new Timestamp(nowDate.getTime());
//             将固定需要维护的字段加入 jsonObj,  , modified
//            jsonObj.put("modified", nowTime);
            String params = "";
            Set set = jsonObj.keySet();
            Object[] objArr = jsonObj.values().toArray();
            for (Object obj1 : set) {
                Object tempobject = jsonObj.get(obj1);
                params = params + "" + obj1 + " = ?,";

            }
            params = params.substring(0, params.length() - 1);

            for (int i = 0; i < objArr.length; i++) {
                if (objArr[i] instanceof String) {
                    if (regexDate.regexDate(((String) objArr[i]))) {
                        Date date2 = fastformat.parse(((String) objArr[i]));
                        objArr[i] = date2;
                    }
                }
            }

            String sql = "update " + tableName + " set " + params + " where id = ? ";
            log.debug("======================>"+jsonObj.toString());
            int code = QueryEngine.getInstance().executeUpdate(sql, ArrayUtils.add(objArr, id));
        }
        return dataArr.size();
    }


}
